
SNFOptions = { ["DebugLevel"] = 0, ["ActiveBid"] = 0, ["Status"] = "On", ["version"] = "2.0",};

local tSNFDKP_Defaults = {
	["1.0"] = {
		["DebugLevel"] = 0,
		["ActiveBid"] = 0,
		["version"] = "1.0",
	},
	["2.0"] = {
		["DebugLevel"] = 0,
		["ActiveBid"] = 0,
		["version"] = "2.0",
	},
	["1.0t"] = {
		["DebugLevel"] = 3,
		["ActiveBid"] = 0,
		["version"] = "1.0t",
	},

};

function SNFCheckDefaults()
	if not SNFDKP_Options then
		SNFOptions = tSNFDKP_Defaults[SNFGetVersion()]
		SNFDEBUG(1, "SNFDKP: Options initialized to default values")
	end
end

local function ParseEditCommand(cmd)
	if cmd == "edit" or cmd == "e" then
		SNFDEBUG(0, "Usage: /snf [e|edit] <command> <data>")
		SNFDEBUG(0, "  edit [set raid|s r] <raidid> sets the raid id to edit")
		SNFDEBUG(0, "  edit [add\124a] <winner> <bid> <item>")
		SNFDEBUG(0, "  edit [att\124attend] <whichlist> <player>[,<player>]")
		SNFDEBUG(0, "  edit [rem\124remove] <whichlist> <player>[,<player>]")
		SNFDEBUG(0, "  edit set correction  -- CAREFUL, this zeroes out everyone's current DKP by applying a correction factor")
		return true
	end
	local str = strmatch(cmd, "edit (.*)$")
	if not str then
		str = strmatch(cmd, "e (.*)$")
	end
	if str then
		if str == "set correction" then
			SNFAttend:SetCorrection()
			SNFDEBUG(0, "Correction factors have been applied")
			return true
		end
		local raid = strmatch(str, "set raid (.*)$")
		if not raid then
			raid = strmatch(str, "s r (.*)$")
		end
		if raid then
			SNFCheckDefaults()
			SNFOptions["editraid"] = raid
			SNFDEBUG(0, "Edit raid marked as "..(SNFOptions["editraid"] or "nil"))
			return true
		end
		local winner, bid, item = strmatch(str, "add (.-) (.-) (.*)$")
		if not (winner and bid and item) then
			winner, bid, item = strmatch(str, "a (.-) (.-) (.*)$")
		end

		if winner and bid and item then
			if not SNFOptions or not SNFOptions["editraid"] then
				SNFDEBUG(0, "You have not set a raid to edit.  Use /snf edit set raid <raidid>")
				return true
			end
			SNFAddEditItem(SNFOptions["editraid"], winner, bid, item)
			return true
		end
		local list, players = strmatch(str, "att (.-) (.*)$")
		if not (list and players and item) then
			list, players = strmatch(str, "attend (.-) (.*)$")
		end
		local use_list = nil
		if list and players then
			if  SNFOptions and SNFOptions["editraid"]  then
				if list == "start" or list == "Start" or list == "start_in" or list == "Start_in" then
					use_list = "start_in"
				end
				if list == "end" or list == "End" or list == "end_in" or list == "End_in" then
					use_list = "end_in"
				end
				if list == "start_wait" or list == "sw" then
					use_list = "start_wait"
				end
				if list == "end_wait" or list == "ew" then
					use_list = "end_wait"
				end
				if use_list then
					SNFDEBUG(0, "Adding '"..(players or "nil").."' to "..use_list.." for raid "..SNFOptions["editraid"])
					SNFAttend:AddRaidList(SNFOptions["editraid"], use_list, players)
					return true
				else
					SNFDEBUG(0, "Unrecognized list: "..(list or "nil"))
					return true
				end
			else
				SNFDEBUG(0, "You must set a raid to edit with /snf edit set raid <raidid>")
				return true
			end
		end

		local list, player = strmatch(str, "rem (.-) (.*)$")
		if not (list and players and item) then
			list, player = strmatch(str, "remove (.-) (.*)$")
		end
		local use_list = nil
		if list and player then
			if  SNFOptions and SNFOptions["editraid"]  then
				if list == "start" or list == "Start" or list == "start_in" or list == "Start_in" then
					use_list = "start_in"
				end
				if list == "end" or list == "End" or list == "end_in" or list == "End_in" then
					use_list = "end_in"
				end
				if list == "start_wait" or list == "sw" then
					use_list = "start_wait"
				end
				if list == "end_wait" or list == "ew" then
					use_list = "end_wait"
				end
				if use_list then
					SNFDEBUG(0, "Removing '"..(player or "nil").."' from "..use_list.." for raid "..SNFOptions["editraid"])
					SNFAttend:RemoveRaidList(SNFOptions["editraid"], use_list, player)
					return true
				else
					SNFDEBUG(0, "Unrecognized list: "..(list or "nil"))
					return true
				end
			else
				SNFDEBUG(0, "You must set a raid to edit with /snf edit set raid <raidid>")
				return true;
			end
		end
	end
end

local function ParseListCommand(cmd)
	if cmd == "list" then
		SNFDEBUG(0, "Usage: /snf list [bids||loot||raids||raid members||safe]")
		SNFDEBUG(0, "  list bids  is only useful during an auction")
		SNFDEBUG(0, "  list bids o  will put the list bids information into officer chat")
		SNFDEBUG(0, "  list loot  gives all loot history for a raid")
		SNFDEBUG(0, "  list raids  lists the raids you have data for")
		SNFDEBUG(0, "  list raid members [raidid] lists the start, end, and wait lists for a raid")
		SNFDEBUG(0, "  list safe  shows the people you will take sync data from")
		SNFDEBUG(0, "  list attend <Name>  shows the attendance for <Name> Capitalization is important")
		SNFDEBUG(0, "  list loot count <Name> <BidLevel> mostly used for debugging loot counts")
		SNFDEBUG(0, "  list dkp  lists everyone in the database along with their DKP count")
		SNFDEBUG(0, "       NOTE: Anyone you put on your safe list could potentially screw up your data")
		return true
	end
	if str == "raid members" or str == "r m" then
		SNFAttend:ListRaidMembers()
		return true
	end
	if cmd == "list loot" then
		SNFDEBUG(0, "Usage: /snfdkp list loot <raidid|name>  (player loot format needs to be improved, sorry!)")
		return true
	end

	if cmd == "list dkp" then
		SNFAttend:ListDKP()
		return true
	end


--[[	if cmd == "list full attend" then
		SNFGetFullAttendanceReport(false)
		return true;
	end

	if cmd == "list full attend r" then
		SNFGetFullAttendanceReport(true)
		return true;
	end
--]]
	local str = strmatch(cmd, "list raid members (.*)$")
	if str then
		SNFAttend:ListRaidMembers(str)
		return true
	end

	local name, bidlevel = strmatch(cmd, "list loot count (.-) (.*)$")
	if name then
		local res = SNFLoot:GetLootCount(name, bidlevel, nil)
		SNFDEBUG(0, "SNFLoot:GetLootCount("..(name or "nil")..","..(bidlevel or "nil")..") = "..(res or "nil"))
		return true
	end

	str = strmatch(cmd, "list loot (.*)$")
	if str then
		if SNFAttend:IsRaid(str) then
			SNFDKP_ListHistoricBids(str)
			return true
		elseif SNFLoot:HasLoot(str) then
			SNFLoot:ListPastLoot(str)
			return true
		end
		SNFDEBUG(0, "No raid or player found named '"..(str or nil).."'")
		return true;
	end

	str = strmatch(cmd, "list attend (.*)$")
	if str then
		SNFAttend:ListRaidsAttended(str)
		return true
	end

	str = strmatch(cmd, "list (.*)$")
	if str == "bids o" then
		SNFDKP_ListLootCouncilSummary()
		return true
	end
	if str == "bids o2" then
		SNFDKP_ListLootCouncilSummary2()
		return true
	end
	if str == "bids o3" then
		SNFDKP_ListLootCouncilSummary3()
		return true
	end
	if str == "bids" then
		SNFDKP_ListActiveBids()
		return true
	end
	if str == "raids" then
		SNFAttend:ListRaids()
		return true
	end
	if str == "safe" then
		SNF_ListSafeSyncSenders()
		return true
	end

	if str == "version" then
		SNFDEBUG(0, "Your SNFDKP version can handle smart v2 syncing")
		return true
	end

	return false
end

local function ParseRaidCommand(cmd)


	if cmd == "raid" then
		SNFDEBUG(0, "Usage: /snfdkp raid [start||end||delete||sync||scan]")
		SNFDEBUG(0, "  raid start [raidid] sets you up to start recording raid drops. Start list is captured")
		SNFDEBUG(0, "  raid end captures raid end list")
		SNFDEBUG(0, "  raid delete <raidid> will remove raid data from your saved data")
		SNFDEBUG(0, "  raid sync <raidid>|all will start to send raid data to members of your party or raid")
		SNFDEBUG(0, "  raid scan <raidid>|all will populate individual user data. This is what feeds the counts of loot drops")
		return true
	end

	local str = strmatch(cmd, "raid (.*)$")
	if str then
		local sub = strmatch(str, "start (.*)$")
		if sub then
			SNFDEBUG(0, "Starting Raid "..(sub or "<none>"))
			if (SNFAttend:StartRaid(sub, true)) then
				SNFDEBUG(0, "Raid started")
			else
				SNFDEBUG(0, "Raid start failed")
			end
			return true
		end
		if str == "start" then
			if (SNFAttend:StartRaid("", true)) then
				SNFDEBUG(0, "Raid started")
			else
				SNFDEBUG(0, "Raid start failed")
			end
			return true
		end
		if str == "end" then
			SNFAttend:SNFEndRaid()
			return true
		end
		if str == "autosync" or str == "as" then
			SNFSmartSync:StartAutoSync()
			return true
		end
		local sub = strmatch(str, "delete all but (.*)$")
		if sub then
			SNFAttend:DeleteAttendBut(sub)
			return true
		end
		local sub = strmatch(str, "delete all before (.*)$")
		if sub then
			SNFAttend:DeleteAttendBefore(sub)
			return true
		end
		local sub = strmatch(str, "delete (.*)$")
		if sub then
			SNFAttend:DeleteAttend(sub)
			return true
		end
		local sub = strmatch(str, "sync (.*)$")
		if sub == "all" then
			SNFDEBUG(0, "Syncing all raids")
			SNFSmartSync:RaidSync("all")
			SNFDEBUG(0, "Full Raid sync queued.")
			return true
		elseif sub then
			SNFDEBUG(0, "Syncing Raid "..(sub or "<none>"))
			SNFSmartSync:RaidSync(sub)
			SNFDEBUG(0, "Raid sync queued.")
			return true
		end
		local sub = strmatch(str, "scan (.*)$")
		if sub == "all" then
			SNFDEBUG(0, "Scanning all raids")
			SNFLoot:ScanAllRaids()
			SNFDEBUG(0, "Full Raid scan completed.")
			return true
		elseif sub then
			SNFDEBUG(0, "Scanning Raid "..(sub or "<none>"))
			SNFLoot:ScanPastRaid(sub)
			SNFDEBUG(0, "Raid scan completed.")
			return true
		end
	end
	return false
end

local function ParseSetCommand(cmd)
	if cmd == "set" then
		SNFDEBUG(0, "Usage: /snf set [option] [value]")
		SNFDEBUG(0, "Usage:  set debug [0-4] - sets the debug level of the mod.  0 is lowest")
		SNFDEBUG(0, "Usage:  set safe <name> allows name to update your data when they initiate a sync")
		SNFDEBUG(0, "Usage:  set unsafe <name> removes name from your list of safe sync senders")
		return
	end
	local str = strmatch(cmd, "set (.*)$")
	if str then
		if str == "test off" then
			SNFOptions["TestStatus"] = "OFF"
			SNFDEBUG(0, "Test status turned off");
			return true
		end
		if str == "test on" then
			SNFOptions["TestStatus"] = "ON"
			SNFDEBUG(0, "Test status turned on");
			return true
		end
		if str == "sync off" then
			SNFOptions["SyncStatus"] = "OFF"
			return true
		end
		if str == "sync on" then
			SNFOptions["SyncStatus"] = "ON"
			return true
		end
		if str == "sort off" then
			SNFOptions["SortStatus"] = "OFF"
			return true
		end
		if str == "sort on" then
			SNFOptions["SortStatus"] = "ON"
			return true
		end
		local sub = strmatch(str, "debug ([0-9]*)")
		if sub then
			d = tonumber(sub)
			if d and d <= 4 and d >= 0 then
				SNFOptions["DebugLevel"] = d
				SNFDEBUG(0, "SNFDKP: DebugLevel set to "..d);
				return true
			end
		end
		local sub = strmatch(str, "^safe (.*)$")
		if sub then
			SNFAddSafeSender(sub)
			return true
		end
		local sub = strmatch(str, "^unsafe (.*)$")
		if sub then
			SNFRemoveSafeSender(sub)
			return true
		end
		SNFDEBUG(0,"SnFDKP: Set option not recognized ("..(cmd or "nil")..")")
		return
	end
end

local function ParseAliasCommand(cmd)
	if cmd == "alias" then
		SNFDEBUG(0, "Usage: /snf alias <main> <alt>")
		SNFDEBUG(0, "Usage:  This command sets up an alias so any references to <alt> are attributed to <main>")
		SNFDEBUG(0, "Usage: /snf alias remove <alt>")
		SNFDEBUG(0, "Usage:  This simply removes an existing alias")
		return
	end
	local alt = strmatch(cmd, "^alias remove (.*)$")
	if alt then
		SNFPlayer:RemoveAlias(alt)
		return true
	end

	local main, alt = strmatch(cmd, "^alias (.*) (.*)$")
	if main and alt then
		if not SNFPlayer:AddAlias(main, alt) then
			SNFDEBUG(0, "Alias failed")
		end
		return true
	end

end

local function ParseFilterCommand(cmd)
	if cmd == "filter" then
		SNFDEBUG(0, "Usage: /snf filter attend <>= comparevalue")
		SNFDEBUG(0, "Usage: /snf filter attend !")
		SNFDEBUG(0, "Usage:  This command sets up a filter")
		SNFDEBUG(0, "Usage:  The only supported filters right now are attend and loot")
		SNFDEBUG(0, "Usage:  Attendance filters should be set back 1 month, loot filters 2 months.")
		SNFDEBUG(0, "Usage:  Example: Set the attendance filter to only raids after 090601:")
		SNFDEBUG(0, "Usage:  /snf filter attend > 20090601")
		SNFDEBUG(0, "Usage:  To clear a filter: /snf filter attend !")
		return
	end

	local filter = strmatch(cmd, "^filter (.-) !$")
	if (filter) then
		SNFFilter:RemoveFilter(filter)
		SNFDEBUG(0, "Filter "..filter.." removed.")
		return true
	end

	local filter, criteria, compareval = strmatch(cmd, "^filter (.-) ([<>=]) (.*)$")
	if not (filter and criteria and compareval) then
		return false
	end
	return SNFFilter:SetFilter(filter, criteria, compareval)
end

--function SNFDKP_Options(arg1,...)
function SNFDKP_Options(arg1)

	if not arg1 or arg1 == "" or arg1 == "help" then
		SNFDEBUG(0, "Usage: /SNFDKP on|off - controls whether the mod is tracking drops and chat")
		SNFDEBUG(0, "       /SNFDKP set [option] [value] - use '/SNFDKP show' to set the list of options that can be set")
		SNFDEBUG(0, "       /SNFDKP raid  - to see raid commands")
		SNFDEBUG(0, "       /SNFDKP list  - to see list commands")
		--SNFDEBUG(0, "       SNFDKP ")
		return
	end
	if arg1 == "off" and not (SNFOptions["Status"] == "off") then
		SNFDKP_Unregister()
		SNFDEBUG(0, "Turned off");
		return
	end
	if arg1 == "on" and not (SNFOptions["Status"] == "on") then
		SNFDKP_Register()
		SNFDEBUG(0, "Turned on");
		return
	end

	if ParseListCommand(arg1) then return end

	if ParseRaidCommand(arg1) then return end

	if ParseSetCommand(arg1) then return end

	if ParseAliasCommand(arg1) then return end

	if ParseFilterCommand(arg1) then return end

	if ParseEditCommand(arg1) then return end

--	if ParseSyncCommand(arg1) then return end

--	if arg1 == "migrate" then
--		SNFAttend:MigrateOldData(SNFRaids)
--		return true;
--	end

	if arg1 == "reload" then
		SNFDEBUG(0, "Reloading guild tab information")
		GuildRoster()
		return true
	end

	if arg1 == "reset" then
		SNFDEBUG(0, "Resetting guild tab information")
		SNFResetPlayerData()
		return true
	end

	if arg1 == "new" then
		SNFDEBUG(0, "Added List loot count command (see /snf list)")
		SNFDEBUG(0, "Bids sorted properly for UPG/BIS (most likely people now at the top)")
		SNFDEBUG(0, "DKP calculations in list bids o fixed")
		--SNFDEBUG(0, "List loot count command (see /snf list)")
		--SNFDEBUG(0, "List loot count command (see /snf list)")
	end
	if arg1 == "ta" then
		local f = SNFAttend:GenerateRaidChecksum1("20100401")
		return true
	end
	if arg1 == "tb" then
		--SNFSmartSync:SyncRaid("Ulduar_20090514", SNFRaids["Ulduar_20090514"])
--		SNFSmartSync:QueueSync("raids", "Ulduar_20090514")
		return true
	end
	if arg1 == "tc" then
--		SNFSmartSync:SyncAuctions("Ulduar_20090514", SNFAuctions["Ulduar_20090514"])
--		SNFSmartSync:QueueSync("auctions", "Ulduar_20090514")
		return true
	end
	if arg1 == "td" then
--		SNFSmartSync:QueueSync("raids", "Ulduar_20090514")
--		SNFSmartSync:QueueSync("auctions", "Ulduar_20090514")
		return true
	end

	SNFDEBUG(0,"Command not recognized ("..arg1..")")
end

function SNFGetDebugLevel()
	return SNFOptions["DebugLevel"] or 0;
end

function SNFGetSyncStatus()
	return SNFOptions["SyncStatus"] or "OFF";
end

function SNFGetTestStatus()
	return SNFOptions["TestStatus"] or "OFF";
end

function SNF_CheckSortStatus()
	return SNFOptions["SortStatus"] or "ON"
end

-- Don't just let anyone send you updates.  This uses a list stored in options to verify
-- that the sender can update your data.
function SNFCheckTrustSync(name)
	local list = SNFOptions["SafeSyncSenders"]

	if list then
		for _, valid in ipairs(list) do
			if name == valid then return true end
		end
	end
	SNFDEBUG(4, "Sender "..(name or "nil").." not on safe senders list")
	return false
end

function SNFAddSafeSender(name)
	if not SNFOptions["SafeSyncSenders"] then SNFOptions["SafeSyncSenders"] = { } end

	table.insert(SNFOptions["SafeSyncSenders"], name)
	SNFDEBUG(0, name.." added to Safe sync senders list")
	return true
end

function SNFRemoveSafeSender(name)
	if not SNFOptions["SafeSyncSenders"] then SNFOptions["SafeSyncSenders"] = { } end

	for key,val in ipairs(SNFOptions["SafeSyncSenders"]) do
		if val == name then
			local ret = table.remove(SNFOptions["SafeSyncSenders"], key)
			SNFDEBUG(1, "Removed "..(ret or "nil"))
			return true
		end
	end
	return false
end

function SNF_ListSafeSyncSenders()
	if not SNFOptions["SafeSyncSenders"] then SNFOptions["SafeSyncSenders"] = { } end

	local init = false

	for _, name in ipairs(SNFOptions["SafeSyncSenders"]) do
		if not init then
			SNFDEBUG(0, "Safe Sync Senders:")
			init = true
		end
		SNFDEBUG(0, "  "..name)
	end

	if not init then
		SNFDEBUG(0, "No one is on your safe sync senders list")
	end
end

